package com.googlecode.animator.view.viewport
{
	import com.googlecode.animator.data.Notifications;
	import com.googlecode.animator.data.cameras.ActualViewCameraVO;
	import com.googlecode.animator.data.cameras.CameraVO;
	import com.googlecode.animator.data.objects3d.CameraProxyVO;
	import com.googlecode.animator.data.objects3d.Object3DVO;
	import com.googlecode.animator.data.objects3d.TargetProxyVO;
	import com.googlecode.animator.model.Animator3DPlayerProxy;
	
	import org.puremvc.as3.multicore.interfaces.INotification;
	import org.puremvc.as3.multicore.interfaces.IProxy;
	import org.puremvc.as3.multicore.patterns.mediator.Mediator;
	
	/**
	 * Ties in the Viewport component with the PureMVC framework. 
	 * @author USER
	 * 
	 */
	public class ViewportMediator extends Mediator
	{
		/**
		 * Produces a unique number to be appended to this mediator's name.
		 */
		public static var count:int = 0;
		
		/**
		 * Identifier. 
		 */
		public static const NAME:String = "ViewportMediator";
		
		protected var _currentCamera:String = "default_camera_5";
		
		protected var _cameraProxy:String;
		
		protected var _targetProxy:String;
		
		/**
		 * Constructor.
		 * @param viewComponent
		 * 
		 */
		public function ViewportMediator(viewComponent:Viewport)
		{
			var name:String = NAME + "_" + count;
			
			super(name, viewComponent);
						
			count ++;
			
			
		}
		
		//////////////////////////////////////////////////////////////////////
		//
		// PureMVC
		//
		//////////////////////////////////////////////////////////////////////
		
		/**
		 * Triggered by PureMVC framework. 
		 * 
		 */
		override public function onRegister():void
		{
			sendNotification(Notifications.VIEWPORT_ADDED);
		}
		
		/**
		 * Clean up. 
		 * 
		 */
		override public function onRemove():void
		{
			
		}
		
		/**
		 * Lists notification of interests. 
		 * @return 
		 * 
		 */
		override public function listNotificationInterests():Array
		{
			var list:Array = super.listNotificationInterests();

			list.push(Notifications.SCENE_ADDED);
			list.push(Notifications.CAMERA_ADDED);
			list.push(Notifications.CAMERA_PROXIES_ADDED);
			list.push(Notifications.OBJECT3D_ADDED);
			list.push(Notifications.OBJECT3D_POSITION_CHANGED);
			
			return list;
		}
		
		/**
		 * Handles notification of interests. 
		 * @param notification
		 * 
		 */
		override public function handleNotification(notification:INotification):void
		{
			super.handleNotification(notification);

			switch(notification.getName())
			{
				 case Notifications.SCENE_ADDED:

					handleSceneAdded();
					
					break;
					
				case Notifications.CAMERA_ADDED:

					handleCameraAdded(notification.getBody() as CameraVO);
					
					break;
				
				case Notifications.CAMERA_PROXIES_ADDED:

					handleCameraProxiesAdded();
					
					break;
				
				case Notifications.OBJECT3D_ADDED:

					handleObject3DAdded(notification.getBody() as Object3DVO);

					break;
				
				case Notifications.OBJECT3D_POSITION_CHANGED:

					handleObject3DPositionChanged(notification.getBody() as ActualViewCameraVO);

					break;	
				
			}
		}
		
		//////////////////////////////////////////////////////////////////////
		//
		// PureMVC: handlers
		//
		//////////////////////////////////////////////////////////////////////
		
		/**
		 * Once the scene and renderer have been added to the model,
		 * they can be added to the viewport itself. 
		 * 
		 */
		protected function handleSceneAdded():void
		{	
			viewRef.setupViewport();
			viewRef.scene = settings.scene;
			viewRef.renderer = settings.renderer;


		}
		
		protected function handleCameraAdded(camera:CameraVO):void
		{
			_currentCamera = camera.name;
		}
		
		/**
		 * In this version there is only one camera. The viewport camera has to be
		 * updated according to its settings. 
		 * @param camera
		 * 
		 */
		protected function handleCameraProxiesAdded():void
		{

			var camera:CameraVO = settings.getCamera(_currentCamera);
			var cameraProxy:CameraProxyVO = settings.getObject3D(_cameraProxy) as CameraProxyVO;
			var targetProxy:TargetProxyVO = settings.getObject3D(_targetProxy) as TargetProxyVO;
			
			camera.x = cameraProxy.x;
			camera.y = cameraProxy.y;
			camera.z = cameraProxy.z;
			
			camera.target.x = targetProxy.x;
			camera.target.y = targetProxy.y;
			camera.target.z = targetProxy.z;
			
			
			viewRef.updateViewportCamera(camera);

		}
		
		/**
		 * Handles the addition of a new DisplayObject3D. 
		 * @param object3D
		 * 
		 */
		protected function handleObject3DAdded(object3D:Object3DVO):void
		{
			if(object3D is CameraProxyVO)
			{
				_cameraProxy = object3D.name;
			}
			
			if(object3D is TargetProxyVO)
			{
				_targetProxy = object3D.name;
			}

			viewRef.render();
		}
		
		/**
		 * Handles the change in position of a 3D camera. 
		 * @param name
		 * 
		 */
		protected function handleCameraPositionChanged(name:String):void
		{
			/* var camera:CameraVO = settings.getCamera(name);

			if(camera.name == viewRef.currentCamera)
			{
				viewRef.updateViewportCamera(camera);
				viewRef.render();
			} */
		}
			
		/**
		 * Triggered by the movement of an object3D. 
		 * @param evt
		 * 
		 */
		protected function handleObject3DPositionChanged(camera:ActualViewCameraVO):void
		{
			viewRef.updateViewportCamera(camera);
			viewRef.render();
		}
		
		//////////////////////////////////////////////////////////////////////
		//
		// Viewport functions
		//
		//////////////////////////////////////////////////////////////////////
		

			
		//////////////////////////////////////////////////////////////////////
		//
		// Camera functions
		//
		//////////////////////////////////////////////////////////////////////
			
		/**
		 * Updates 3D camera for the viewport. 
		 * @param camera
		 * 
		 */
		protected function updateCamera(camera:CameraVO):void
		{
			viewRef.updateViewportCamera(camera);				
			
		}
		
		//////////////////////////////////////////////////////////////////////
		//
		// Utility functions
		//
		//////////////////////////////////////////////////////////////////////
		
		/**
		 * Returns typed reference to the model. 
		 * @return 
		 * 
		 */
		protected function get settings():Animator3DPlayerProxy
		{
			var proxy:IProxy = facade.retrieveProxy(Animator3DPlayerProxy.NAME);
			
			return proxy as Animator3DPlayerProxy;
		}
		
		/**
		 * Returns a typed reference to the Viewport component. 
		 * @return 
		 * 
		 */
		protected function get viewRef():Viewport
		{
			return viewComponent as Viewport;
		}
	}
}